mod lexer;
mod parser;
mod formatter;

use std::env;
use std::fs;
use lexer::Token;
use parser::ParseResult;

fn main() {
    let args: Vec<String> = env::args().collect();
    // read from file passed as first argument, else read stdin
    let input = if args.len() >= 2 {
        fs::read_to_string(&args[1]).expect("Failed to read file")
    } else {
        // read stdin
        use std::io::Read;
        let mut s = String::new();
        std::io::stdin().read_to_string(&mut s).expect("Failed to read stdin");
        s
    };

    // Lex
    let mut lx = lexer::Lexer::new(&input);
    lx.lex();

    // If lexer errors -> print them and exit (these were type A in your original)
    if !lx.errors.is_empty() {
        for e in &lx.errors {
            eprintln!("{}", e);
        }
        return;
    }

    // Parse
    let tokens = lx.tokens.clone(); // tokens include kind, text, line
    let mut prs = parser::Parser::new(tokens);
    let res = prs.parse_compunit();

    // If parser collected errors -> print Error type B lines
    if !prs.errors.is_empty() {
        for e in prs.errors {
            println!("{}", e);
        }
        return;
    }

    // Successful parse -> format
    match res {
        ParseResult::Ok(ast) => {
            let formatted = formatter::format_program(&ast);
            println!("{}", formatted);
        }
        ParseResult::Err(msgs) => {
            for m in msgs {
                println!("{}", m);
            }
        }
    }
}